/**************************************************************************//**
 * @item     CosyOS-II Kernel
 * @file     os_handler.c
 * @brief    OS_SysTick_Handler and sPendSV_Handler
 * @author   迟凯峰
 * @version  V3.4.0
 * @date     2025.01.06
 ******************************************************************************/

#include "os_link.h"

#if SYSCFG_DEBUGGING == __ENABLED__
static s_u32_t usedtime[2] = {0};
#endif

void OS_SysTick_Handler(void) MCUCFG_SYSTICK_ATTRIBUTE
{
	s_u8_t _SYS_REG_ i;
	#if SYSCFG_SYSTICKTIME_COUNT == __ENABLED__
	static m_tick_t tick_temp;
	#endif
	
	/* 清除中断标志位 */
	mSysTick_Clear;
	
	/* 系统滴答时间统计开始 */
	#if SYSCFG_SYSTICKTIME_COUNT == __ENABLED__
	if(s_sign_taskmgr){
		tick_temp = mSysTick_Counter;
	}
	#endif
	
	/* 软件RTC */
	#if SYSCFG_SOFTRTC == __ENABLED__
	if(true){
		static
		#if SYSCFG_SYSTICKCYCLE > 1000000UL / 65536
		s_u16_t
		#else
		s_u32_t
		#endif
		_SYS_MEM_ counter = 0;
		if(s_sign_every.set){
			s_sign_every.set = false;
			counter = 0;
		}
		else{
			if(counter < 1000000UL / SYSCFG_SYSTICKCYCLE - 1){
				counter++;
				if(counter == 1000000UL / SYSCFG_SYSTICKCYCLE / 2){
					s_sign_every.halfsec = true;
				}
			}
			else{
				counter = 0;
				s_sign_every.halfsec = true;
				s_sign_every.second = true;
				if(s_rtc.second < 59) s_rtc.second++;
				else{
					s_rtc.second = 0;
					s_sign_every.minute = true;
					if(s_rtc.minute < 59) s_rtc.minute++;
					else{
						s_rtc.minute = 0;
						s_sign_every.hour = true;
						if(s_rtc.hour < 23) s_rtc.hour++;
						else{
							s_rtc.hour = 0;
							s_sign_every.day = true;
							if(s_rtc.day < 7) s_rtc.day++;
							else s_rtc.day = 1;
							if(s_rtc.date < (s_rtc.month == 2 ? s_month2day : s_month0day[s_rtc.month])) s_rtc.date++;
							else{
								s_rtc.date = 1;
								s_sign_every.month = true;
								if(s_rtc.month < 12) s_rtc.month++;
								else{
									s_rtc.month = 1;
									s_sign_every.year = true;
									if(s_rtc.year < 99) s_rtc.year++;
									else{
										s_rtc.year = 0;
										s_rtc.yeah++;
									}
								}
							}
						}
					}
				}
				#if SYSCFG_GETRTC_INT == __ENABLED__
				s_update_rtccopy();
				#endif
			}
		}
	}
	#endif
	
	/* 运行时间统计 */
	#if SYSCFG_RUNTIME_COUNT == __ENABLED__
	if(true){
		static
		#if SYSCFG_SYSTICKCYCLE > 1000000UL / 65536
		s_u16_t
		#else
		s_u32_t
		#endif
		_SYS_MEM_ counter = 0;
		if(counter < 1000000UL / SYSCFG_SYSTICKCYCLE - 1){
			counter++;
		}
		else{
			counter = 0;
			if(s_runtime.second < 59) s_runtime.second++;
			else{
				s_runtime.second = 0;
				if(s_runtime.minute < 59) s_runtime.minute++;
				else{
					s_runtime.minute = 0;
					if(s_runtime.hour < 23) s_runtime.hour++;
					else{
						s_runtime.hour = 0;
						s_runtime.day++;
					}
				}
			}
		}
	}
	#endif
	
	#if SYSCFG_DEBUGGING == __ENABLED__
	if(s_sign_debug_send){
		s_sign_debug_send = false;
		tTimQry_ms(OS_TMID_DEBUGHOOK, 30);
	}
	if(s_sign_debug_recv){
		s_sign_debug_recv = false;
		tTimInt_ms(OS_TMID_DEBUGGER, 15);
	}
	#endif
	
	/* 滴答钩子 */
	#if SYSCFG_TICKHOOK == __ENABLED__
	tick_hook();
	#endif
	
	/* 定时中断 */
	#if OS_TIMINTTOTAL
	i = OS_TIMINTTOTAL;
	while(i--){
		if(s_timint_handle[i]->timer){
			s_timint_handle[i]->timer--;
			if(!s_timint_handle[i]->timer){
				if(s_timint_handle[i]->autoreload){
					s_timint_handle[i]->timer = s_timint_handle[i]->reload;
				}
				if(s_timint_handle[i]->hookortask){
					sResumeTask_TimInt(i);
				}
				else{
					sCallHook_TimInt(i);
				}
			}
		}
	}
	#endif
	
	/* 定时查询 */
	#if OS_TIMQRYTOTAL
	i = OS_TIMQRYTOTAL;
	while(i--){
		if(s_timqry_handle[i]->timer && s_timqry_handle[i]->timer < (s_timqry_t)~0){
			s_timqry_handle[i]->timer--;
		}
		if(!s_timqry_handle[i]->timer){
			if((*s_timqry_handle[i]->event)()){
				if(s_timqry_handle[i]->autoreload){
					s_timqry_handle[i]->timer = s_timqry_handle[i]->reload;
				}
				else{
					s_timqry_handle[i]->timer = ~0;
				}
				if(s_timqry_handle[i]->hookortask){
					sResumeTask_TimQry(i);
				}
				else{
					sCallHook_TimQry(i);
				}
			}
		}
	}
	#endif
	
	/* 延时定时器 */
	if(true){
		s_tasknode_tsp _SYS_REG_ node_curr;
		i = (s_u8_t)SYSCFG_TASKPRIORITY;
		__TASKQUE_NEXT:
		do{
			node_curr = s_taskque_head[--i];
		}while(node_curr == OS_NULL);
		while(true){
			if(node_curr->status == OS_STATUS_BLOCKED){
				if(node_curr->timer && node_curr->timer < (s_delay_t)~0){
					node_curr->timer--;
				}
			}
			if(node_curr == s_taskque_head[i]->last){
				if(!i) break;
				goto __TASKQUE_NEXT;
			}
			else{
				node_curr = node_curr->next;
			}
		}
		if(s_sign_ready_delay){
			if(s_task_current->timer && s_task_current->timer < (s_delay_t)~0){
				s_task_current->timer--;
				if(!s_task_current->timer){
					s_sign_ready_delay = false;
				}
			}
		}
	}
	
	/* 时间片计数 */
	#if SYSCFG_SAMEPRISCHEDULE == __TIMESHARING__
	if(s_task_current->tc_counter < (s_sharing_t)~0){
		s_task_current->tc_counter++;
	}
	#endif
	
	/* 安全运行时 */
	#if SYSCFG_SAFERUNTIME == __ENABLED__
	if(s_task_current->pri && s_task_current->saferuntime){
		s_task_current->srt_counter++;
		if(s_task_current->srt_counter > 1UL * s_task_current->saferuntime * OS_TIMESHARING(s_task_current)){
			s_task_current->status = OS_STATUS_OVERTIME;
			s_sign_timeout[s_task_current->tid] = true;
			#if SYSCFG_DEBUGGING == __ENABLED__
			s_alarm.timedout_saferuntime = true;
			#endif
		}
	}
	#endif
	
	/* 任务管理器相关 */
	#if SYSCFG_DEBUGGING == __ENABLED__
	if(s_sign_taskmgr){
		usedtime[0]++; /*!< CPU使用时间计数 */
		#if SYSCFG_SYSTICKTIME_COUNT == __ENABLED__
		mSysTick_Counting; /*!< 系统滴答时间统计 */
		#endif
	}
	#endif
	
	/* 定时调度（触发完整调度）*/
	s_sign_schedule_all = true;
	s_sign_schedule = true;
	if(!s_sign_schedule_forbid){
		mPendSV_Set;
	}
}

s_tasknode_tsp  _SYS_MEM_ s_task_news = OS_NULL;
#if SYSCFG_DEBUGGING == __ENABLED__
m_stacksize_t   _SYS_MEM_ s_taskstacklen;
#endif

#if SYSCFG_MCUCORE == 80251
#pragma functions(static)
#endif
s_u8_t sPendSV_Handler(void) MCUCFG_C51USING
{
	/* 中断挂起服务_FIFO */
	#if MCUCFG_PENDSVFIFO_DEPTH > 0
	mPendSV_FIFOHandle;
	#endif
	
	/* 中断挂起服务_FLAG */
	#if SYSCFG_PENDSVHOOK == __ENABLED__
	pendsv_hook();
	#endif
	
	/* 更新全局变量副本 */
	#if SYSCFG_GETRTC_INT == __ENABLED__
	if(s_sign_rtc){
		s_sign_rtc = false;
		s_update_rtccopy();
	}
	#endif
	#if SYSCFG_COPYHOOK == __ENABLED__
	sUpdateCopy(copy_hook());
	#endif
	
	/* 每PendSV监控（假定入栈）*/
	#if SYSCFG_DEBUGGING == __ENABLED__
	if(s_task_current != OS_NULL){
		if(s_task_current->stacklen_max < s_taskstacklen){
			s_task_current->stacklen_max = s_taskstacklen;
			if(s_task_current->stacksize < s_taskstacklen){
				s_alarm.overflow_taskstack_future = true;
			}
		}
	}
	#endif
	
	/* 任务调度 */
	if(s_sign_schedule_forbid) return 0;
	if(s_sign_schedule){
		s_u8_t _SYS_MEM_ pri;
		s_tasknode_tsp _SYS_REG_ node_buff[2];
		#define node_curr        node_buff[0]    /*!< 当前节点 */
		#define node_news        node_buff[1]    /*!< 新加节点 */
		m_bit_t sign_x = false;
		#define sign_expired     sign_x          /*!< 到期信号（时间片已到期）*/
		#define sign_push        sign_x          /*!< 入栈信号 */
		#if SYSCFG_DEBUGGING == __ENABLED__
		m_tick_t _SYS_REG_ tick_counter;
		#endif
		s_sign_schedule = false;
		
		/* 启动任务 */
		if(s_task_starter != OS_NULL){
			if(s_taskque_len < OS_TASKQUEUELEN_MAX){
				/* 静态创建 */
				if(*s_task_starter->dualhandle != OS_NULL){
					node_news = (s_tasknode_tsp)s_task_starter;
					if(node_news->stacksize < MCUCFG_BASICSTACKSIZE){
						#if SYSCFG_DEBUGGING == __ENABLED__
						s_fault.failed_startuptask = true;
						s_fault.overflow_taskstack = true;
						#endif
						s_startup_code = OS_ECODE_OVERFLOW_TASKSTACK;
						goto __STARTUP_END;
					}
					else{
						mTaskStack_INIT;
					}
				}
				/* 动态创建 */
				else{
					node_news = OS_NULL;
					node_news = (s_tasknode_tsp)s_malloc(sizeof(s_tasknode_ts));
					if(node_news != OS_NULL){
						node_news->stacksize = s_task_starter->stacksize;
						if(node_news->stacksize < MCUCFG_BASICSTACKSIZE){
							node_news->stacksize = MCUCFG_BASICSTACKSIZE;
							node_news->create = 2;
						}
						else{
							node_news->create = 1;
						}
						node_news->bsp = OS_NULL;
						node_news->bsp = (s_u8_t _MALLOC_MEM_ *)s_malloc(node_news->stacksize);
						if(node_news->bsp != OS_NULL){
							mTaskStack_INIT;
							node_news->tid = s_task_starter->tid;
							node_news->opri = s_task_starter->opri;
							node_news->dualhandle = s_task_starter->dualhandle;
							*node_news->dualhandle = node_news;
							#if SYSCFG_DEBUGGING == __ENABLED__
							node_news->name = s_task_starter->name;
							#endif
							#if SYSCFG_SAFERUNTIME == __ENABLED__
							node_news->saferuntime = s_task_starter->saferuntime;
							#endif
						}
						else{
							s_free(node_news);
							#if SYSCFG_DEBUGGING == __ENABLED__
							s_fault.failed_startuptask = true;
							s_fault.mallocfailed_taskstack = true;
							#endif
							s_startup_code = OS_ECODE_MALLOCFAIL_TASKSTACK;
							goto __STARTUP_END;
						}
					}
					else{
						#if SYSCFG_DEBUGGING == __ENABLED__
						s_fault.failed_startuptask = true;
						s_fault.mallocfailed_tasknode = true;
						#endif
						s_startup_code = OS_ECODE_MALLOCFAIL_TASKNODE;
						goto __STARTUP_END;
					}
				}
				/* 公共部分 */
				if(node_news->opri <= (s_u8_t)(SYSCFG_TASKPRIORITY - 1)){
					node_news->pri = node_news->opri;
				}
				else{
					node_news->pri = SYSCFG_TASKPRIORITY - 2;
					#if SYSCFG_DEBUGGING == __ENABLED__
					s_alarm.outrange_taskpriority = true;
					#endif
				}
				node_news->status = s_task_status0;
				node_news->blocktype = 0;
				node_news->timer = 0;
				node_news->handle = OS_NULL;
				#if SYSCFG_SAMEPRISCHEDULE == __TIMESHARING__
				node_news->tc_counter = 0;
				#endif
				#if SYSCFG_DEBUGGING == __ENABLED__
				node_news->usedtime[0] = 0;
				node_news->usedtime[1] = 0;
				node_news->stacklen_max = MCUCFG_BASICSTACKSIZE;
				#endif
				#if SYSCFG_SAFERUNTIME == __ENABLED__
				node_news->srt_counter = 0;
				#endif
				/* 新任务加入任务队列 */
				s_insert_taskque(node_news);
				s_taskque_len++;
				s_startup_code = OS_ECODE_NOERROR;
			}
			else{
				#if SYSCFG_DEBUGGING == __ENABLED__
				s_fault.failed_startuptask = true;
				s_alarm.overflow_taskqueue = true;
				#endif
				s_startup_code = OS_ECODE_OVERFLOW_TASKQUEUE;
			}
			__STARTUP_END:
			s_task_starter = OS_NULL;
			if(s_sign_return){
				if(node_news == u_taskhandle_Sysidle){
					s_sign_return = false;
					node_news = u_taskhandle_Starter;
					goto __NEWTASK_PREPROCESS; /*!< 首次任务调度 -> 新任务预处理 */
				}
				else{
					return 0;
				}
			}
			else if(!s_sign_schedule_all){
				s_switch_ready(node_news);
				s_sign_schedule = false;
			}
		}
		
		/* 调度类型 */
		/* 1、完整调度：从任务队列头节点开始查找就绪 */
		if(s_sign_schedule_all){
			s_sign_schedule_all = false;
			s_sign_switch_prigroup = false;
			s_task_switch = OS_NULL;
			pri = (s_u8_t)SYSCFG_TASKPRIORITY;
			do{
				node_curr = s_taskque_head[--pri];
			}while(node_curr == OS_NULL);
		}
		/* 2、立即切换：从切换任务或其优先级组首节点开始查找就绪 */
		else if(s_task_switch != OS_NULL){
			if(s_sign_switch_prigroup){
				s_sign_switch_prigroup = false;
				node_curr = s_taskque_head[s_task_switch->pri];
			}
			else{
				node_curr = s_task_switch;
			}
			s_task_switch = OS_NULL;
		}
		/* 3、立即返回：立即返回至当前任务继续运行 */
		#if SYSCFG_SAMEPRISCHEDULE == __COOPERATIVE__
		else if(s_task_current->status == OS_STATUS_READY){
		#elif SYSCFG_SAMEPRISCHEDULE == __TIMESHARING__
		else if(s_task_current->status == OS_STATUS_READY && s_task_current->tc_counter < OS_TIMESHARING(s_task_current)){
		#endif
			goto __TASKING_RETURN;
		}
		/* 4、当前调度：从当前任务或其优先级组首节点开始查找就绪 */
		else{
			#if SYSCFG_SAMEPRISCHEDULE == __COOPERATIVE__
			node_curr = s_taskque_head[s_task_current->pri];
			#elif SYSCFG_SAMEPRISCHEDULE == __TIMESHARING__
			node_curr = s_task_current;
			#endif
		}
		pri = node_curr->pri;
		/* 开始调度：更新任务状态并同步查找最高优先级的就绪任务 */
		while(true){
			switch(node_curr->status){
				/* 就绪状态 */
				case OS_STATUS_READY:{
					#if SYSCFG_SAMEPRISCHEDULE == __COOPERATIVE__
					if(true){
						goto __READY_NOW;
					}
					#elif SYSCFG_SAMEPRISCHEDULE == __TIMESHARING__
					/* 时间片未到期 */
					if(node_curr->tc_counter < OS_TIMESHARING(node_curr)){
						goto __READY_NOW;
					}
					/* 时间片已到期（到期任务必为该优先级组首节点）*/
					else{
						sign_expired = true;
						node_curr->tc_counter = 0;
						node_news = node_curr; /* 缓存该任务 */
						goto __BACKWARD;
					}
					#endif
				}
				/* 阻塞状态
				   定时器为0 -> 变为就绪
				   超时阻塞: 阻塞条件已解除 -> 变为就绪
				             阻塞条件未解除 -> 节点后移
				   延时阻塞: -> 节点后移
				*/
				case OS_STATUS_BLOCKED:{
					if(!node_curr->timer) goto __BECOME_READY;
					else if(node_curr->blocktype != OS_BLOCKED_DELAY){
						switch(node_curr->blocktype & 0x0F){
						case 0x01: if( *(s_u8_t  *)node_curr->handle) goto __BECOME_READY; break;
						case 0x02: if( *(s_u16_t *)node_curr->handle) goto __BECOME_READY; break;
						case 0x04: if( *(s_u32_t *)node_curr->handle) goto __BECOME_READY; break;
						case 0x0F: if(!*(s_u8_t  *)node_curr->handle) goto __BECOME_READY; break;
						}
					}
					goto __BACKWARD;
				}
				/* 超时状态 */
				#if SYSCFG_SAFERUNTIME == __ENABLED__
				case OS_STATUS_OVERTIME:{
					if(!s_sign_timeout[node_curr->tid]) goto __BECOME_READY;
					goto __BACKWARD;
				}
				#endif
				/* 删除状态 */
				case OS_STATUS_DELETED:{
					if(node_curr->create){
						s_free(node_curr->bsp);
						*node_curr->dualhandle = OS_NULL;
						s_free(node_curr);
					}
					if(s_remove_taskque(node_curr)){
						node_curr = s_taskque_head[pri]->last;
					}
					s_taskque_len--;
					goto __BACKWARD;
				}
				/* 其它状态 */
				default:{
					goto __BACKWARD;
				}
			} /* 变为就绪 */
			__BECOME_READY:{
				node_curr->status = OS_STATUS_READY;
				#if SYSCFG_SAMEPRISCHEDULE == __TIMESHARING__
				node_curr->tc_counter = 0;
				#endif
			} /* 已经就绪 */
			__READY_NOW:{
				node_news = node_curr;
				break;
			} /* 节点后移 */
			__BACKWARD:{
				if(node_curr == s_taskque_head[pri]->last){
					#if SYSCFG_SAMEPRISCHEDULE == __TIMESHARING__
					if(sign_expired) break; /* 在该优先级组中，未能找到时间片未到期的就绪任务，继续已到期的就绪任务（已缓存至 node_news）*/
					#endif
					do{
						node_curr = s_taskque_head[--pri];
					}while(node_curr == OS_NULL);
				}
				else{
					node_curr = node_curr->next;
				}
			}
		}
		
		if(true){
			/* 新任务仍为当前任务 -> 返回 */
			if(node_news == s_task_current){
				goto __TASKING_RETURN;
			}
			/* 新任务轮转至其优先级组首节点 */
			#if SYSCFG_SAMEPRISCHEDULE == __TIMESHARING__
			else if(node_news != s_taskque_head[pri]){
				s_taskque_head[pri] = node_news;
			}
			#endif
		}
		
		/* 当前任务后处理 */
		if(true){
			#if SYSCFG_SAMEPRISCHEDULE == __TIMESHARING__
			sign_push = false;
			#endif
			if(s_task_current->status < OS_STATUS_STOPPED){
				/* 入栈监控 */
				#if SYSCFG_DEBUGGING == __ENABLED__
				if(s_task_current->stacksize < s_taskstacklen){
					#if MCUCFG_TASKSTACK_REALLOC == __ENABLED__
					if(s_task_current->create){
						s_task_current->stacksize = s_taskstacklen + MCUCFG_TASKSTACKREALLOC_INC;
						s_free(s_task_current->bsp);
						s_task_current->bsp = OS_NULL;
						s_task_current->bsp = (s_u8_t _MALLOC_MEM_ *)s_malloc(s_task_current->stacksize);
						if(s_task_current->bsp != OS_NULL){
							sign_push = true;
							s_task_current->create = 2;
							s_alarm.realloc_taskstack = true;
						}
						else{
							s_task_current->status = OS_STATUS_STOPPED_TSRF;
							s_fault.reallocfailed_taskstack = true;
						}
					}
					else{
						s_task_current->status = OS_STATUS_STOPPED_TSOF;
						s_fault.overflow_taskstack = true;
					}
					#else
					s_task_current->status = OS_STATUS_STOPPED_TSOF;
					s_fault.overflow_taskstack = true;
					#endif
				}
				else{
					sign_push = true;
				}
				#else
				sign_push = true;
				#endif
			}
		}
		
		/* 新任务预处理 */
		__NEWTASK_PREPROCESS:{
			#if SYSCFG_DEBUGGING == __ENABLED__
			if(s_sign_taskmgr) tick_counter = mSysTick_Counter;
			#endif
		}
		
		/* 当前任务入栈 */
		if(sign_push){
			#if SYSCFG_SAFERUNTIME == __ENABLED__
			if(s_task_current->pri > node_news->pri){
				s_task_current->srt_counter = 0;
			}
			#endif
			#if SYSCFG_DEBUGGING == __ENABLED__
			if(s_sign_taskmgr) mUsedTime_END;
			#endif
			mUserReg_CSave;
		}
		
		/* 新任务出栈 */
		if(true){
			if(node_news->blocktype != OS_BLOCKED_DELAY){
				mSysIRQ_Disable;
			}
			#if SYSCFG_DEBUGGING == __ENABLED__
			if(s_sign_taskmgr) mUsedTime_INIT;
			#endif
			mUserReg_CRes;
			s_task_news = node_news;
		}
		
		if(sign_push) return 2;
		else return 1;
	}
	
	__TASKING_RETURN:{
		if(s_task_current->blocktype != OS_BLOCKED_DELAY){
			mSysIRQ_Disable;
		}
		return 0;
	}
}
